先简单汇总一些本部分的内容:
内置高阶组件 | 作用 | 配置项 |
---|---|---|
configureStore | 封装版的 createStore(简化配置) | reducer、middleware、devTools |
createSlice | 在原 reducer 拆分思想不变的情况下将单个模块汇于一个文件(减少模板文件) | name、initialState、reducers、extraReducers |
createAsyncThunk | 用于解决 RTK 中单个模块的异步任务(内置 redux-thunk 包) |
# 1、基本介绍
Redux Toolkit 是 Redux 官方推荐的编写 Redux 逻辑的标准方法。用于解决:
- 配置 Redux 存储太复杂
- Redux 需要太多样板代码
- 必须添加很多包才能让 Redux 做任何有用的事情
Redux Toolkit 包括强大的数据获取和缓存功能,我们称之为“RTK 查询”。因此,在很多地方,我们将 Redux Toolkit 简称为 RTK。
# 2、安装使用
npm install @reduxjs/toolkit react-redux
前面我们已经学到了 react-redux 有 Provide
、connect()
、 等高阶组件用于将 react 和 redux 关联
下面我们将利用 RTK 中的 configureStore
、createSlice
、createAsyncThunk
等 API 来简化原 redux 高级 API 使用时的代码模板
RTK 快速入门:Usage Guide (opens new window)
# 3、configureStore
configureStore 对 createStore 进行了包装,其提供了简化的配置选项并提供了良好的默认值:
在 RTK 中,redux-thunk 默认使用,并且默认开启了 redux-devtools
原来 redux 的实现方式
使用的是 redux 中的 applyMiddleware 和 compose
import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'react-thunk'
import reducer from './reducer.js'
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
export default createStore(reducer, composeEnhancers(applyMiddleware(thunk)))
configureStore 函数接收一个对象,其对象中包含 reducer、middleware、devTools 三大选项
// @/store/index.js
import { configureStore } from '@reduxjs/toolkit'
import cartReducer from './features/cart.js'
export default configureStore({
reducer: {
cart: cartReducer
}
})
# 4、createSlice ✨
createSlice 可以简化以前使用 redux 的 combineReducers
的模块化方案
├── store
├── index.js
└── featres
├── cart.js
└── products.js
createSlice 函数接收一个对象,其对象中包含 name、initialState、reducers 三大选项
// features/cart.js
import { createSlice } from '@reduxjs/toolkit'
const cartSlice = createSlice({
name: 'cart',
initialState: {
counter: 1
},
reducers: {
countChangeAction(state, action) {
// 传递参数的默认选项为 payload
state.counter = eval(state.counter + action.payload) // RTK 底层使用了immerjs库来保证的数据不可变性(immutablejs也可以实现相同的功能)
}
}
})
export const { countChangeAction } = cartSlice.actions
export default cartSlice.reducer
使用示例
import { connect } from 'react-redux'
// 仅仅这里不一样而已😂
import { countChangeAction } from '@/store/features/cart.js'
class Left extends React.PureComponent {
upDownHandle(str) {
this.props.countChange(str)
}
render() {
const { count } = this.props
return (
<div>
<p>left couter: {count}</p>
<button onClick={(e) => this.upDownHandle('+1')}>+1</button>
<button onClick={(e) => this.upDownHandle('+3')}>+3</button>
</div>
)
}
}
// ==============
const mapStateToProps = (state) => ({
count: state.cart.counter
})
const mapDispatchToProps = (dispatch) => ({
countChange: function (str) {
dispatch(countChangeAction(str))
}
})
export default connect(mapStateToProps, mapDispatchToProps)(Demo)
# 5、createAsyncThunk
createAsyncThunk 可以简化以前使用 redux 的 applyMiddleware
添加 redux-thunk 来增强原 redux 功能,可以实现异步请求相同的功能
promise 的三种状态:pending、fulfilled、rejected
// features/cart.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
// 创建一个action 并导出
export const getListDataAction = createAsyncThunk('getListData', async (payload, extraInfo) => {
const res = await axios.get('/data.json')
return res.data
})
const cartSlice = createSlice({
name: 'cart',
initialState: {
dataList: []
},
reducers: {},
// 方式1(动态函数名)
extraReducers: {
[getListDataAction.fulfilled](state, action) {
state.dataList = action.payload
}
}
// 方式2(链式调用)
extraReducers: (builder) => {
builder.addCase(getListDataAction.fulfilled, (state, action) => {
state.dataList = action.payload
})
}
})
export default cartSlice.reducer